import { format, isToday, isYesterday, isThisWeek, isThisMonth, parseISO, formatDistance } from 'date-fns';
import { zhCN } from 'date-fns/locale';
import { clsx, type ClassValue } from 'clsx';

// CSS类名合并工具
export function cn(...inputs: ClassValue[]) {
  return clsx(inputs);
}

// 日期格式化工具 - 使用 date-fns
export function formatDate(date: Date | string, formatStr: string = 'PPP'): string {
  const dateObj = typeof date === 'string' ? parseISO(date) : date;
  return format(dateObj, formatStr, { locale: zhCN });
}

// 相对时间格式化
export function formatRelativeDate(date: Date | string): string {
  const dateObj = typeof date === 'string' ? parseISO(date) : date;
  
  if (isToday(dateObj)) {
    return '今天';
  }
  
  if (isYesterday(dateObj)) {
    return '昨天';
  }
  
  if (isThisWeek(dateObj)) {
    return format(dateObj, 'EEEE', { locale: zhCN });
  }
  
  if (isThisMonth(dateObj)) {
    return format(dateObj, 'M月d日', { locale: zhCN });
  }
  
  return format(dateObj, 'yy年M月d日', { locale: zhCN });
}

// 时间格式化
export function formatTime(date: Date | string): string {
  const dateObj = typeof date === 'string' ? parseISO(date) : date;
  return format(dateObj, 'HH:mm');
}

// 相对时间格式化（更精确）
export function formatRelativeTime(date: Date): string {
  const now = new Date();
  const diff = now.getTime() - date.getTime();
  const seconds = Math.floor(diff / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);

  if (days > 0) return `${days}天前`;
  if (hours > 0) return `${hours}小时前`;
  if (minutes > 0) return `${minutes}分钟前`;
  return '刚刚';
}

// 金币数量格式化
export function formatCoinAmount(amount: number): string {
  if (amount >= 10000) {
    return `${(amount / 10000).toFixed(1)}万`;
  }
  if (amount >= 1000) {
    return `${(amount / 1000).toFixed(1)}k`;
  }
  return amount.toString();
}

// 金币变化格式化（带符号和颜色）
export function formatCoinChange(amount: number): {
  text: string;
  sign: '+' | '-' | '';
  color: string;
  isPositive: boolean;
} {
  if (amount > 0) {
    return {
      text: formatCoinAmount(amount),
      sign: '+',
      color: 'text-green-500',
      isPositive: true
    };
  } else if (amount < 0) {
    return {
      text: formatCoinAmount(Math.abs(amount)),
      sign: '-',
      color: 'text-red-500',
      isPositive: false
    };
  } else {
    return {
      text: '0',
      sign: '',
      color: 'text-gray-500',
      isPositive: true
    };
  }
}

// 货币格式化
export function formatCurrency(amount: number): string {
  return new Intl.NumberFormat('zh-CN').format(amount);
}

// 生成随机ID
export function generateId(): string {
  return Date.now().toString(36) + Math.random().toString(36).substr(2);
}

// 获取日期范围
export function getDateRange(days: number): { start: Date; end: Date } {
  const end = new Date();
  const start = new Date();
  start.setDate(end.getDate() - days);
  start.setHours(0, 0, 0, 0);
  end.setHours(23, 59, 59, 999);
  return { start, end };
}

// 按日期分组
export function groupByDate<T extends { timestamp: Date }>(items: T[]): Record<string, T[]> {
  return items.reduce((groups, item) => {
    const dateKey = item.timestamp.toISOString().split('T')[0];
    if (!groups[dateKey]) {
      groups[dateKey] = [];
    }
    groups[dateKey].push(item);
    return groups;
  }, {} as Record<string, T[]>);
}

// 生成颜色
export function generateColors(count: number): string[] {
  const colors = [
    '#10B981', '#3B82F6', '#8B5CF6', '#F59E0B',
    '#EF4444', '#06B6D4', '#84CC16', '#F97316',
    '#6366F1', '#EC4899'
  ];
  
  if (count <= colors.length) {
    return colors.slice(0, count);
  }
  
  // 如果需要更多颜色，生成随机颜色
  const result = [...colors];
  while (result.length < count) {
    const hue = Math.floor(Math.random() * 360);
    result.push(`hsl(${hue}, 70%, 50%)`);
  }
  
  return result;
}

// 防抖函数
export function debounce<T extends (...args: any[]) => any>(
  func: T,
  wait: number
): (...args: Parameters<T>) => void {
  let timeout: NodeJS.Timeout;
  return (...args: Parameters<T>) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), wait);
  };
}

// 节流函数
export function throttle<T extends (...args: any[]) => any>(
  func: T,
  limit: number
): (...args: Parameters<T>) => void {
  let inThrottle: boolean;
  return (...args: Parameters<T>) => {
    if (!inThrottle) {
      func(...args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}

// 深拷贝
export function deepClone<T>(obj: T): T {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj.getTime()) as T;
  if (obj instanceof Array) return obj.map(item => deepClone(item)) as T;
  if (typeof obj === 'object') {
    const cloned = {} as T;
    Object.keys(obj).forEach(key => {
      (cloned as any)[key] = deepClone((obj as any)[key]);
    });
    return cloned;
  }
  return obj;
}

// 图片处理
export function compressImage(
  file: File,
  maxWidth: number = 800,
  maxHeight: number = 600,
  quality: number = 0.8
): Promise<string> {
  return new Promise((resolve) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();
    
    img.onload = () => {
      // 计算新的尺寸
      let { width, height } = img;
      
      if (width > height) {
        if (width > maxWidth) {
          height = (height * maxWidth) / width;
          width = maxWidth;
        }
      } else {
        if (height > maxHeight) {
          width = (width * maxHeight) / height;
          height = maxHeight;
        }
      }
      
      canvas.width = width;
      canvas.height = height;
      
      // 绘制并压缩
      ctx?.drawImage(img, 0, 0, width, height);
      const compressedDataUrl = canvas.toDataURL('image/jpeg', quality);
      resolve(compressedDataUrl);
    };
    
    img.src = URL.createObjectURL(file);
  });
}

// 从粘贴事件获取图片
export async function getImageFromPaste(event: ClipboardEvent): Promise<string | null> {
  const items = Array.from(event.clipboardData?.items || []);
  const imageItem = items.find(item => item.type.indexOf('image') !== -1);
  
  if (imageItem) {
    const file = imageItem.getAsFile();
    if (file) {
      return await compressImage(file);
    }
  }
  
  return null;
}

// 颜色工具
export const colors = {
  primary: {
    50: '#eff6ff',
    100: '#dbeafe',
    500: '#3b82f6',
    600: '#2563eb',
    700: '#1d4ed8',
  },
  gray: {
    50: '#f9fafb',
    100: '#f3f4f6',
    200: '#e5e7eb',
    300: '#d1d5db',
    400: '#9ca3af',
    500: '#6b7280',
    600: '#4b5563',
    700: '#374151',
    800: '#1f2937',
    900: '#111827',
  },
  success: {
    50: '#ecfdf5',
    100: '#d1fae5',
    500: '#10b981',
    600: '#059669',
  },
  error: {
    50: '#fef2f2',
    100: '#fee2e2',
    500: '#ef4444',
    600: '#dc2626',
  },
  warning: {
    50: '#fffbeb',
    100: '#fef3c7',
    500: '#f59e0b',
    600: '#d97706',
  },
};

// 动画配置
export const animations = {
  spring: {
    type: 'spring',
    stiffness: 300,
    damping: 30,
  },
  smooth: {
    type: 'tween',
    duration: 0.3,
    ease: [0.25, 0.46, 0.45, 0.94],
  },
  bouncy: {
    type: 'spring',
    stiffness: 400,
    damping: 25,
  },
};

// 常用的过渡动画
export const transitions = {
  fadeIn: {
    initial: { opacity: 0 },
    animate: { opacity: 1 },
    exit: { opacity: 0 },
    transition: animations.smooth,
  },
  slideUp: {
    initial: { opacity: 0, y: 20 },
    animate: { opacity: 1, y: 0 },
    exit: { opacity: 0, y: -20 },
    transition: animations.spring,
  },
  slideDown: {
    initial: { opacity: 0, y: -20 },
    animate: { opacity: 1, y: 0 },
    exit: { opacity: 0, y: 20 },
    transition: animations.spring,
  },
  scale: {
    initial: { opacity: 0, scale: 0.9 },
    animate: { opacity: 1, scale: 1 },
    exit: { opacity: 0, scale: 0.9 },
    transition: animations.bouncy,
  },
};

// 验证函数
export const validate = {
  required: (value: any) => {
    if (typeof value === 'string') {
      return value.trim().length > 0;
    }
    return value !== null && value !== undefined;
  },
  
  minLength: (value: string, min: number) => {
    return value.length >= min;
  },
  
  maxLength: (value: string, max: number) => {
    return value.length <= max;
  },
  
  number: (value: any) => {
    return !isNaN(Number(value));
  },
  
  positiveNumber: (value: any) => {
    const num = Number(value);
    return !isNaN(num) && num > 0;
  },
  
  integer: (value: any) => {
    const num = Number(value);
    return !isNaN(num) && Number.isInteger(num);
  },
};